package cn.cjxy.springboot_zonghe_practice.service.impl;

import cn.cjxy.springboot_zonghe_practice.domain.Dept;
import cn.cjxy.springboot_zonghe_practice.domain.Employee;
import cn.cjxy.springboot_zonghe_practice.domain.OperationLog;
import cn.cjxy.springboot_zonghe_practice.domain.EmployeeVO;
import cn.cjxy.springboot_zonghe_practice.mapper.DeptMapper;
import cn.cjxy.springboot_zonghe_practice.mapper.EmpMapper;
import cn.cjxy.springboot_zonghe_practice.query.BaseQuery;
import cn.cjxy.springboot_zonghe_practice.service.EmployeeService;
import cn.cjxy.springboot_zonghe_practice.service.OperationLogService;
import cn.cjxy.springboot_zonghe_practice.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 员工服务实现类
 * 实现员工的增删改查、分页查询、批量操作、统计查询等功能
 * 包含业务逻辑校验和操作日志记录
 * 
 * @author huangjie
 * @since 2025-07-06
 */
@Service
public class EmployeeServiceImpl implements EmployeeService {
    
    /**
     * 员工数据访问层
     */
    @Autowired
    private EmpMapper empMapper;
    
    /**
     * 部门数据访问层
     */
    @Autowired
    private DeptMapper deptMapper;
    
    /**
     * 操作日志服务，用于记录所有操作
     */
    @Autowired
    private OperationLogService operationLogService;

    /**
     * 添加员工
     * 业务规则：
     * 1. 身份证号不能重复
     * 2. 手机号不能重复
     * 
     * @param employee 员工信息对象
     * @return 操作结果
     */
    @Override
    public R addEmployee(Employee employee) {
        // 校验身份证唯一性
        Integer idCardCount = empMapper.selectEmployeeByIdCard(employee.getIdcard());
        if (idCardCount > 0) {
            return R.fail("身份证号已存在!");
        }
        
        // 校验手机号唯一性
        Integer phoneCount = empMapper.selectEmployeeByPhone(employee.getPhone());
        if (phoneCount > 0) {
            return R.fail("手机号已存在!");
        }
        
        // 新增：支持前端传部门名
        if (employee.getDeptId() == null && employee.getDeptName() != null && !employee.getDeptName().trim().isEmpty()) {
            Dept dept = deptMapper.selectDeptByName(employee.getDeptName());
            if (dept == null) {
                dept = new Dept();
                dept.setDeptName(employee.getDeptName());
                deptMapper.addDept(dept);
            }
            employee.setDeptId(dept.getId());
        }
        
        empMapper.addEmployee(employee);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("添加");
        log.setObjectType("员工");
        log.setObjectId(employee.getId());
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("添加员工:" + employee.getName());
        operationLogService.log(log);
        
        return R.ok();
    }

    /**
     * 修改员工信息
     * 业务规则：
     * 1. 身份证号不能与其他员工重复（排除自己）
     * 2. 手机号不能与其他员工重复（排除自己）
     * 
     * @param employee 员工信息对象（必须包含id）
     * @return 操作结果
     */
    @Override
    public R updateEmployee(Employee employee) {
        // 校验身份证唯一性（排除自己）
        Integer idCardCount = empMapper.selectEmployeeByIdCardAndNotId(employee.getIdcard(), employee.getId());
        if (idCardCount > 0) {
            return R.fail("身份证号已存在!");
        }
        
        // 校验手机号唯一性（排除自己）
        Integer phoneCount = empMapper.selectEmployeeByPhoneAndNotId(employee.getPhone(), employee.getId());
        if (phoneCount > 0) {
            return R.fail("手机号已存在!");
        }
        
        empMapper.updateEmployee(employee);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("修改");
        log.setObjectType("员工");
        log.setObjectId(employee.getId());
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("修改员工:" + employee.getName());
        operationLogService.log(log);
        
        return R.ok();
    }

    /**
     * 根据ID删除员工
     * 业务规则：有部门的员工不可以被删除
     * 
     * @param id 员工ID
     * @return 操作结果
     */
    @Override
    public R deleteEmployeeById(Long id) {
        // 查询员工信息
        Employee employee = empMapper.selectEmployeeById(id);
        if (employee == null) {
            return R.fail("员工不存在!");
        }
        
        // 检查员工是否有部门，有部门的员工不可以被删除
        if (employee.getDeptId() != null) {
            return R.fail("有部门的员工不可以被删除!");
        }
        
        empMapper.deleteEmployeeById(id);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("删除");
        log.setObjectType("员工");
        log.setObjectId(id);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("删除员工ID:" + id);
        operationLogService.log(log);
        
        return R.ok();
    }

    /**
     * 根据ID查询员工信息
     * 
     * @param id 员工ID
     * @return 查询结果，包含员工详细信息
     */
    @Override
    public R selectEmployeeById(Long id) {
        Employee employee = empMapper.selectEmployeeById(id);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("查询");
        log.setObjectType("员工");
        log.setObjectId(id);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("查询员工ID:" + id);
        operationLogService.log(log);
        
        return R.ok(employee);
    }

    /**
     * 分页查询员工
     * 
     * @param query 分页查询参数，包含页码和每页大小
     * @return 分页结果，包含员工列表、总数、当前页码、每页大小
     */
    @Override
    public R selectEmployeeByPage(BaseQuery query) {
        List<EmployeeVO> employees = empMapper.selectEmployeeVOByPage(query.getStart(), query.getPageSize());
        Integer total = empMapper.selectEmployeeCount();
        
        Map<String, Object> result = new HashMap<>();
        result.put("list", employees);
        result.put("total", total);
        result.put("currentPage", query.getCurrentPage());
        result.put("pageSize", query.getPageSize());
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("查询");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("分页查询员工，页码:" + query.getCurrentPage() + "，每页大小:" + query.getPageSize());
        operationLogService.log(log);
        
        return R.ok(result);
    }

    /**
     * 批量添加员工
     * 业务规则：
     * 1. 身份证号不能重复
     * 2. 手机号不能重复
     * 
     * @param employees 员工列表
     * @return 操作结果
     */
    @Override
    public R batchAddEmployee(List<Employee> employees) {
        // 批量校验身份证和手机号唯一性
        for (Employee employee : employees) {
            Integer idCardCount = empMapper.selectEmployeeByIdCard(employee.getIdcard());
            if (idCardCount > 0) {
                return R.fail("身份证号 " + employee.getIdcard() + " 已存在!");
            }
            
            Integer phoneCount = empMapper.selectEmployeeByPhone(employee.getPhone());
            if (phoneCount > 0) {
                return R.fail("手机号 " + employee.getPhone() + " 已存在!");
            }
        }
        
        empMapper.batchAddEmployee(employees);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("批量添加");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("批量添加员工，数量:" + employees.size());
        operationLogService.log(log);
        
        return R.ok();
    }

    /**
     * 批量删除员工
     * 业务规则：有部门的员工不可以被删除
     * 
     * @param ids 员工ID列表
     * @return 操作结果
     */
    @Override
    public R batchDeleteEmployee(List<Long> ids) {
        // 检查是否有员工属于部门
        for (Long id : ids) {
            Employee employee = empMapper.selectEmployeeById(id);
            if (employee != null && employee.getDeptId() != null) {
                return R.fail("员工 " + employee.getName() + " 有部门，不可以被删除!");
            }
        }
        
        empMapper.batchDeleteEmployee(ids);
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("批量删除");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("批量删除员工，数量:" + ids.size());
        operationLogService.log(log);
        
        return R.ok();
    }

    /**
     * 统计各部门人数
     * 返回每个部门的名称和员工数量
     * 
     * @return 统计结果，包含部门名称和员工数量
     */
    @Override
    public R selectDeptEmployeeCount() {
        List<Map<String, Object>> result = empMapper.selectDeptEmployeeCount();
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("统计");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("统计各部门人数");
        operationLogService.log(log);
        
        return R.ok(result);
    }

    /**
     * 统计各部门最高薪水员工
     * 返回每个部门中薪水最高的员工信息
     * 
     * @return 统计结果，包含部门名称、员工姓名、最高薪水
     */
    @Override
    public R selectDeptMaxSalaryEmployee() {
        List<Map<String, Object>> result = empMapper.selectDeptMaxSalaryEmployee();
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("统计");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("统计各部门最高薪水员工");
        operationLogService.log(log);
        
        return R.ok(result);
    }

    /**
     * 统计各部门薪水总和
     * 返回每个部门的薪水总额
     * 
     * @return 统计结果，包含部门名称和薪水总和
     */
    @Override
    public R selectDeptTotalSalary() {
        List<Map<String, Object>> result = empMapper.selectDeptTotalSalary();
        
        // 日志记录
        OperationLog log = new OperationLog();
        log.setOperationType("统计");
        log.setObjectType("员工");
        log.setObjectId(null);
        log.setOperator("system");
        log.setOperationTime(new Date());
        log.setDetails("统计各部门薪水总和");
        operationLogService.log(log);
        
        return R.ok(result);
    }
} 